package com.powerhua.core.base.dao;

import com.powerhua.core.base.BaseModelCacheManager;
import com.powerhua.core.base.bean.IField;
import com.powerhua.core.base.bean.IModel;
import com.powerhua.core.utils.CommonUtils;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.RowMapper;

/**
 *
 * @author Brian.Xie
 */
public class ListDao extends CommonDao {

    private static final Log LOG = LogFactory.getLog(ListDao.class);

    public String list(Map map, String modelId, int pageSize, int pageNum) {
        IModel model = BaseModelCacheManager.getInstance().getModel(modelId);
        if (!checkModel(model)) {
            return "";
        }

        String countSql = "select count(" + model.getPk().getName() + ") from " + model.getModelTable();
        int count = jdbcTemplate.queryForInt(countSql);
        int startNum = pageSize * (pageNum - 1);
        if (startNum > count - 1) {
            return "";
        }

        int lastPage = count / pageSize;
        if (count % pageSize > 0) {
            lastPage++;
        }

        String listSql = "select * from " + model.getModelTable() + " limit " + startNum + "," + pageSize;

        List<String> fieldNames = model.getFieldNames();
        Map<String, IField> fields = model.getFields();
        List<String> colNames = new ArrayList<String>();
        List<String> types = new ArrayList<String>();
        colNames.add(model.getPk().getName());
        types.add(model.getPk().getType());
        if (fields != null && fieldNames != null && fieldNames.size() > 0) {
            //Iterator<Entry<String, IField>> itr = fields.entrySet().iterator();
            for(int i = 0; i < fieldNames.size(); i++) {
                IField field = fields.get(fieldNames.get(i));
                if(field != null) {
                    colNames.add(field.getName());
                    types.add(field.getType());
                } else {
                    LOG.error("can not find the field [" + fieldNames.get(i) + "] in the model [" 
                        + model.getModelId() + "]");
                    return "";
                }
            }
            /*
            while (itr.hasNext()) {
                Entry<String, IField> entry = itr.next();
                colNames.add(entry.getValue().getName());
                types.add(entry.getValue().getType());
            }
            */
        }

        if (colNames.size() == 0) {
            return "";
        }

        List<String> list = jdbcTemplate.query(listSql, new ListMapper(colNames, types));

        int endNum = startNum + pageSize;
        if (endNum > count) {
            endNum = count;
        }
        StringBuffer result = new StringBuffer("[");
        result.append("[");
        result.append(pageSize + ",");
        result.append(pageNum + ",");
        result.append(lastPage + ",");
        result.append((startNum + 1) + ",");
        result.append(endNum + ",");
        result.append(count);
        result.append("]");
        if (list.size() > 0) {
            result.append(",");
            for (int i = 0; i < list.size(); i++) {
                result.append(list.get(i));
                if (i != list.size() - 1) {
                    result.append(",");
                }
            }
        }
        result.append("]");

        return result.toString();
    }

    /**
     * 
     * @param map
     * @param countSql
     * @param listSql
     * @param colNames
     * @param types
     * @param pageSize
     * @param pageNum
     * @return
     */
    public String list(Map map, String countSql, String listSql, List<String> colNames,
        List<String> types, int pageSize, int pageNum) {

        int count = jdbcTemplate.queryForInt(countSql);
        int startNum = pageSize * (pageNum - 1);
        if (startNum > count - 1) {
            return "";
        }
        int lastPage = count / pageSize;
        if (count % pageSize > 0) {
            lastPage++;
        }

        List<String> list = jdbcTemplate.query(listSql, new ListMapper(colNames, types));

        int endNum = startNum + pageSize;
        if (endNum > count) {
            endNum = count;
        }
        StringBuffer result = new StringBuffer("[");
        result.append("[");
        result.append(pageSize + ",");
        result.append(pageNum + ",");
        result.append(lastPage + ",");
        result.append((startNum + 1) + ",");
        result.append(endNum + ",");
        result.append(count);
        result.append("]");
        if (list.size() > 0) {
            result.append(",");
            for (int i = 0; i < list.size(); i++) {
                result.append(list.get(i));
                if (i != list.size() - 1) {
                    result.append(",");
                }
            }
        }
        result.append("]");

        return result.toString();
    }

    /**
     * 内部类
     */
    protected class ListMapper implements RowMapper {

        private List<String> colNames;
        private List<String> types;

        /**
         * 
         * @param colNames
         * @param types
         */
        protected ListMapper(List<String> colNames, List<String> types) {
            this.colNames = colNames;
            this.types = types;
        }

        /**
         *
         * @param rs
         * @param rowNum
         * @return
         * @throws java.sql.SQLException
         */
        @Override
        public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
            StringBuffer result = new StringBuffer("[");
            for (int i = 0; i < colNames.size(); i++) {
                String type = "varchar";
                if (i < types.size()) {
                    type = types.get(i).toLowerCase();
                }
                result.append("'");
                result.append(getResultSetValue(rs, type, colNames.get(i)));
                result.append("'");
                if (i != colNames.size() - 1) {
                    result.append(",");
                }
            }
            result.append("]");

            return new String(result);
        }

        /**
         * 
         * @param rs
         * @param type
         * @param colName
         * @return
         * @throws java.sql.SQLException
         */
        private String getResultSetValue(ResultSet rs, String type, String colName) throws SQLException {
            String result = "";
            if ("timestamp".equals(type)) {
                result = CommonUtils.getDateTimeFormat(rs.getTimestamp(colName));
            } else if ("date".equals(type)) {
                result = CommonUtils.getDateFormat(rs.getTimestamp(colName));
            } else if ("decimal".equals(type)) {
                result = rs.getBigDecimal(colName).toString();
            } else if ("varchar".equals(type)) {
                result = rs.getString(colName);
            } else if ("integer".equals(type) || "int".equals(type)) {
                result = "" + rs.getInt(colName);
            } else if ("bigint".equals(type)) {
                result = "" + rs.getLong(colName);
            } else if ("float".equals(type)) {
                result = "" + rs.getFloat(colName);
            } else if ("double".equals(type)) {
                result = "" + rs.getDouble(colName);
            } else {
                LOG.error("Not support type");
                throw new SQLException("Not support type. type:" + type);
            }
            return result;
        }
    }
}
